
/***************************************************************************
 *   Copyright (C) 1997 to 2004 by Jonathan Duddington                     *
 *   email: jonsd@users.sourceforge.net                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write see:                           *
 *               <http://www.gnu.org/licenses/>.                           *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* Read and convert options files on startup, Options save,
   Edit: Colours, Users, Speech
*/

#include "kernel.h"

#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "dbox.h"
#include "template.h"
#include "werr.h"
#include "font.h"
#include "msgs.h"
#include "flex.h"
#include "os.h"
#include "time.h"
#include "locale.h"

#include "narc.h"
#include "hdrs.h"


extern void (*menu_expected)(int *);

extern char *path_choices;
extern BOX box_table[N_BOXES];
extern int dbox_menu_field;
extern wimp_menustr *wmenu_boxes_names;
extern BLIST mboxlist;
extern char mbox_list[];
extern int text_colrs_256[];
extern int text_colrs_256_inv[];
extern int text_colrs_256_green[];


extern char pluto_articles[128];
extern int  os_version;
extern char os_version_string[8];
extern char *path_choices;
extern char *path_choices2;
extern int pluto_slave;
extern int pluto_lock;
extern char *pluto_name;

extern menu menu_main;
extern menu menu_prefs;



wimp_menustr *wmenu_ntransports;
wimp_menustr *wmenu_mtransports;
wimp_menustr *wmenu_acks;
wimp_menustr *wmenu_edit_styles;
wimp_menustr *wmenu_confirm_delete;
wimp_menustr *wmenu_sig_styles;
wimp_menustr *wmenu_open_thread;
wimp_menustr *wmenu_maillist;
wimp_menustr *wmenu_textwindow;
wimp_menustr *wmenu_skip_thread;
wimp_menustr *wmenu_crossposts;
wimp_menustr *wmenu_hide_box;
wimp_menustr *wmenu_undelivered;
wimp_menustr *wmenu_undeliv_news;
wimp_menustr *wmenu_new_to_unread;
wimp_menustr *wmenu_subset_status;


static dbox dbox_mail=NULL;
int dbox_mail_mail_list_server;
int dbox_mail_tags;
int dbox_mail_box;
int dbox_mail_log;
int dbox_mail_copy_box;

static int mbox_number = 0;
OPTIONS options;
VOICES voices;
int transport_opts=0;
int options_save_flag=0;    /* options file needs to be saved */
extern int ntransport_data[];
extern int mtransport_data[];

typedef struct {
	wimp_menustr **ptr;
	char *name;
	char *string;
} WMENU;

static WMENU wmenu[] = {
	&wmenu_ntransports,   "Transports",    "(none),Voyager,NewsHound,ANT,Termite",
	&wmenu_mtransports,   "Transports",    "(none),Voyager,POP,ANT,Termite,FreeSMTP,POPStar,Hermes",
	&wmenu_edit_styles,   "Edit Style",    "Clipboard,WipeOut,Edit",
	&wmenu_confirm_delete,"Confirm Del",   "Confirm All,Confirm Locked,Allow All",
	&wmenu_sig_styles,    "Tags",          "None,Before--,Sig.Start,Sig.End",
	&wmenu_open_thread,   "Open Thread",   "No,1st Article,1st Unread",
	&wmenu_maillist,      "Mail List",     "No,Manual,Automatic,Private,Restricted",
	&wmenu_textwindow,    "Colour",        "White,Light Grey,Grey,Black,Blue-Green",
	&wmenu_skip_thread,   "Skip Thread",    "Skip,Mark Read,Delete",
	&wmenu_crossposts,    "Crossposts",    "Don't Show,Set Read,Delete,Leave",
	&wmenu_hide_box,      "Hide Box",      "No,Yes,No Unread,No Messages",
	&wmenu_undelivered,   "Unaddressed",   "Deliver,Leave,Discard",
	&wmenu_undeliv_news,  "Unaddressed",   "Deliver,Discard",
	&wmenu_new_to_unread, "New/Unread",    "by Box,by Source,All,None",
	&wmenu_subset_status, "Status",        "All,Unread,Read,Locked,Marked,Lock/Mark,Read/L/M,Replied,Outgoing",
	&wmenu_acks,          "Receipt Ack",   "None,Hold+Open,Hold,Send",
};

static char *maillist_types[] = {"No","Manual","Automatic","Private","Restricted"};
static char *textwindow_colrs[] = {"White","Light Grey","Grey","Black","Blue-Green"};
static char *sig_style_names[] = {"None","Before--","Sig.Start","Sig.End"};
static wimp_menustr *menu_def = NULL;
static char *menu_data = NULL;




int read_os_version()
/*******************/
/* Read the OS version number, OS 3.5 returns 0xa5 */
{
	os_error *error;

	error = os_swi2(0x06+os_X, 0, 0);   /* OS_Byte 0, get os version string */
	memcpy(os_version_string,&error->errmess[8],4);
	os_version_string[4] = 0;

	os_swi3r(0x06, 129, 0, 0xff, NULL, &os_version, NULL);

	return(os_version);
}   /* end of read_os_version */





void options_save()
/*****************/
{
	FILE *f;
	char fname[256];

	if(options.options_version != 20)
	{
		werr(0,"Bad version number in Choices file: %d",options.options_version);
		return;
	}

	sprintf(fname,"%s.choices",path_choices);
	f = fopen_werr(fname,"w","Options ");
	if(f == NULL)
	{
		return;
	}

	fwrite(&options,1,sizeof(options),f);
	fclose(f);

	sprintf(fname,"%s.voices",path_choices);
	f = fopen_werr(fname,"w","Options ");
	if(f == NULL)
	{
		return;
	}

	fwrite(&voices,1,sizeof(voices),f);
	fclose(f);

	options_save_flag = 0;
}   /* end of options_save */






int options_load(void)
/******************/
{
	FILE *f;
	int ix;
	char fname[256];

	sprintf(fname,"%s.choices",path_choices);
	f = fopen_werr(fname,"r","Options ");
	if(f == NULL)
	{
		return(-1);
	}

	fread(&options,1,sizeof(options),f);

	transport_opts = ntransport_data[options.news_transport] | mtransport_data[options.mail_transport];
	fclose(f);

	memset(&voices, 0, sizeof(voices));
	sprintf(fname,"%s.voices",path_choices);
	f = fopen(fname,"r");
	if(f != NULL)
	{
		fread(&voices,1,sizeof(voices),f);
		fclose(f);
	}
	for(ix=0; ix<N_VOICES; ix++)
	{
		if(voices.voicename[ix][0] == 0)
			strcpy(voices.voicename[ix], "default");
	}

	make_mbox_list();
	return(0);
}   /* end of options_load */



void options_default()
/********************/
{
	int  i;

	memset(&options,0,sizeof(options));
	for(i=0; i<4; i++)
	{
		options.d.font[i].spacing = 15*16;
	}
	options.d.text_width = 256;
}   /* end of options_default */





wimp_menustr *make_font_menu(int sys_font)
/****************************************/
{
	os_regset regs;
	os_error *error;
	int menu_def_size;
	int menu_data_size;
	int sys_font_flag=0;

	if(sys_font)
		sys_font_flag = 0x100000;

	regs.r[0] = 0;
	regs.r[1] = 0;
	regs.r[2] = 0x80000 + sys_font_flag;
	regs.r[3] = 0;
	regs.r[4] = 0;
	regs.r[5] = 0;
	regs.r[6] = 0;
	error = os_swix(0x40091,&regs);   /* Font_ListFonts */

	menu_def_size = regs.r[3];
	menu_data_size = regs.r[5];
	menu_def = realloc(menu_def,menu_def_size);
	menu_data = realloc(menu_data,menu_data_size);

	if((menu_def == NULL) || (menu_data == NULL))
	{
		werr(0,"Can't allocate memory to read font list");
		return(NULL);
	}

	regs.r[0] = 0;
	regs.r[1] = (int)menu_def;
	regs.r[2] = 0x80000 + sys_font_flag;
	regs.r[3] = menu_def_size;
	regs.r[4] = (int)menu_data;
	regs.r[5] = menu_data_size;
	regs.r[6] = 0;
	error = os_swix(0x40091,&regs);   /* Font_ListFonts */

	if(error)
	{
		werr(0,error->errmess);
	}

	return(menu_def);
}   /* end of make_font_menu */






/****************************************************************************************/


/********************************************************************************************/






void dbox_mail_selected(int *hits)
/********************************/
{
	int box;

	box = box_lookup_number(hits[0]);

	switch(dbox_menu_field)
	{
	case 4:
		dbox_mail_box = box;
		break;

	case 5:
		dbox_mail_log = box;
		break;

	case 10:
		if(box == BOX_BIN)
			box = -1;
		dbox_mail_copy_box = box+1;
		break;
	}

	dbox_setfield(dbox_mail,dbox_menu_field,get_box_name(box));
	dbox_showstatic(dbox_mail);
}   /* end of dbox_mail_selected */




void selected_user_sig_style(int *hits)
/*************************************/
{
	dbox_mail_tags = hits[0];
	dbox_setfield(dbox_mail,dbox_menu_field,sig_style_names[hits[0]]);
}   /* end of selected_sig_style */




void selected_maillist_type(int *hits)
/************************************/
{
	dbox_mail_mail_list_server = hits[0];
	dbox_setfield(dbox_mail,dbox_menu_field,maillist_types[hits[0]]);
}   /* end of selected_maillisr_type */





BOOL dbox_mail_raw_handler(dbox d, void *event, void *handle)
/***********************************************************/
{
	int  box_control = 0;
	wimp_eventstr *e;
	wimp_mousestr *mouse;

	e = (wimp_eventstr *)event;

	switch (e->e)
	{
	case wimp_EBUT:
		/* click on icon.  get icon number. */
		mouse = &e->data.but.m;
		switch(dbox_menu_field = mouse->i)
		{
		case 10:
			box_control = 0x200;
		case 4:
		case 5:
			if(wmenu_boxes_names == NULL)
				break;

			make_boxes_menu(box_control,NULL);
			dbox_menu(wmenu_boxes_names,dbox_mail_selected,mouse);
			return(TRUE);

		case 7:
			dbox_menu(wmenu_sig_styles,selected_user_sig_style,mouse);
			return(TRUE);

		case 11:
			dbox_menu(wmenu_maillist,selected_maillist_type,mouse);
			return(TRUE);
		}
		break;
	}
	return(help_handler(event,HELP_USER));
}   /* end of dbox_mail_raw_handler */




void check_multiple_domains(void)
/****************************/
{
	int  i;
	int  ix;
	char *domain1;
	char *domain2;
	char user_id[32];

	/* are the users all of the same domain, use full addresses in the users menu if not */
	options.users_menu = 0;
	for(ix=0; ix<mboxlist.n_entries; ix++)
	{
		options.mailbox[ix].flags &= (~4);

		strcpy(user_id,get_user_id(&options.mailbox[ix]));
		if((user_id[0]==0) || (user_id[0]=='@'))
			continue;

		domain1 = strchr(options.mailbox[ix].email_addr,'@');

		if(strchr(user_id,'*') != NULL)
		{
			/* contains wildcard */
			options.mailbox[ix].flags |= 4;
		}

		for(i=0; i<ix; i++)
		{
			if(strcmp(user_id,get_user_id(&options.mailbox[i]))==0)
			{
				/* this user name is not unique, set flag */
				options.mailbox[ix].flags |= 4;
				options.mailbox[i].flags |= 4;
			}

			domain2 = strchr(options.mailbox[i].email_addr,'@');
			if((domain1 != NULL) && (domain2 != NULL) &&
					(strcmp_lc(domain1,domain2) != 0))
			{
				options.users_menu = 1;
			}
		}
	}
}  /* end of check_mulitple_domains */




int check_domain(char *domain)
/*************************/
{
	if(strcmp(domain,"demon.co.uk")==0)
	{
		werr(0,"First part of Domain is missing, before 'demon'");
		return(-1);
	}
	return(0);
}   /* end of check_domain */




void dbox_mail_handler(dbox d, void *handle)
/*********************************************/
{
	OPTIONS_MAILBOX *m;
	int finished = 0;
	int  box;
	int  name_changed;
	char user_id[32];
	char domain[64];
	char buf[128];

	m = &options.mailbox[mbox_number];

	switch(dbox_get(d))
	{
	case 0:
		dbox_getfield(dbox_mail,2,user_id,sizeof(user_id));
		if(user_id[0] <= ' ')
		{
			werr(0,"Bad User Id, must start with a letter");
			break;
		}

		dbox_getfield(dbox_mail,9,buf,sizeof(m->full_name));
		if((buf[0] != 0) && !isalnum(buf[0]))
		{
			werr(0,"Bad Name, must start with a letter");
			break;
		}
		strcpy(m->full_name,buf);

		m->request_acks = dbox_getnumeric(dbox_mail,8);

		dbox_getfield(dbox_mail,3,domain,sizeof(domain));
		if(check_domain(domain) < 0)
			break;
		if((strlen(user_id) + strlen(domain) + 1) >= sizeof(m->email_addr))
		{
			werr(0,"Email address is too long");
			break;
		}

		m->mail_list_server = dbox_mail_mail_list_server;
		m->tags = dbox_mail_tags;
		m->box = dbox_mail_box;
		m->log = dbox_mail_log;
		m->copy_box = dbox_mail_copy_box;

		m->flags = 0;
		if(dbox_getnumeric(dbox_mail,12))
			m->flags |= USEROPT_NONEWS;
		if(dbox_getnumeric(dbox_mail,14))
			m->flags |= USEROPT_NOMAIL;
		if(dbox_getnumeric(dbox_mail,15))
			m->flags |= USEROPT_SIGN;
		if(dbox_getnumeric(dbox_mail,16))
			m->flags |= USEROPT_ENCRYPT;



		sprintf(buf,"%s@%s",user_id,domain);
		name_changed = 0;

		if(validate_email_addr(buf) < 0)
		{
			werr(0,"Bad email address: %s",buf);
			break;
		}

		if(strcmp(buf,m->email_addr) != 0)
		{
			name_changed = 1;
			strcpy(m->email_addr,buf);
		}
		m->user_id_len = strlen(user_id);

		dbox_getfield(dbox_mail,13,m->signature,sizeof(m->signature));
#ifdef deleted
		if(m->signature[0] <= ' ')
		{
			/* no signature set, make it from the user name */
			p = get_user_id(m);
			strnc2py(m->signature,make_legal_fname(p),sizeof(m->signature));
			m->signature[sizeof(m->signature)-1] = 0;
		}
#endif

		make_mbox_list();

		if(name_changed)
			category_add_mail_name(m->email_addr,1);

		/* are the users all of the same domain, use full addresses in the users menu if not */
		check_multiple_domains();

		options_save();

		if(load_boxes_file() == 0)
		{
			box = options.mailbox[mbox_number].box;
			if(box_table[box].default_user == 0)
			{
				box_table[box].default_user = mbox_number+1;
				save_boxes_file();
			}
		}


		if(!dbox_persist()) finished = 1;
		break;

	case 6:   /* edit sig file */
		if(m->email_addr[0] == 0)
		{
			beep();
			break;
		}

		dbox_getfield(dbox_mail,13,buf,sizeof(buf));
		if(buf[0] <= ' ')
		{
			beep();
			break;
		}
		sprintf(buf,"%s.Signatures.%s",path_choices,make_legal_fname(buf));
		dataopen(buf,0xfff);
		break;

	default:
		finished = 1;
		break;
	}

	mbox_open(7);

	if(finished)
		dbox_hide(dbox_mail);
}   /* end of dbox_mail_handler */



void mbox_edit(int mbox)
/**********************/
{
	OPTIONS_MAILBOX *m;

	if(mbox >= N_MAIL_BOX)
		mbox = N_MAIL_BOX - 1;

	mbox_number = mbox;
	m = &options.mailbox[mbox];

	dbox_setfield(dbox_mail,2,get_user_id(m));
	dbox_setfield(dbox_mail,3,get_user_domain(m));
	dbox_setfield(dbox_mail,9,m->full_name);
	dbox_setfield(dbox_mail,4,get_box_name(m->box));
	dbox_setfield(dbox_mail,5,get_box_name(m->log));
	dbox_setfield(dbox_mail,10,get_box_name(m->copy_box-1));
	dbox_setfield(dbox_mail,7,sig_style_names[m->tags]);
	dbox_setnumeric(dbox_mail,8,m->request_acks);
	dbox_setnumeric(dbox_mail,12,m->flags & USEROPT_NONEWS);
	dbox_setnumeric(dbox_mail,14,m->flags & USEROPT_NOMAIL);
	dbox_setnumeric(dbox_mail,15,m->flags & USEROPT_SIGN);
	dbox_setnumeric(dbox_mail,16,m->flags & USEROPT_ENCRYPT);
	dbox_setfield(dbox_mail,11,maillist_types[m->mail_list_server]);
	dbox_setfield(dbox_mail,13,m->signature);

	dbox_mail_mail_list_server = m->mail_list_server;
	dbox_mail_tags = m->tags;
	dbox_mail_box = m->box;
	dbox_mail_log = m->log;
	dbox_mail_copy_box = m->copy_box;

	dbox_hide(dbox_mail);   /* to force it to reopen, in front of other windows */
	dbox_showstatic(dbox_mail);
}   /* end of mbox_edit */




void options_users()
/******************/
{
	mbox_open(1);
}   /* end of options_users */




/********************************************************************************/


/********************************************************************************/


static dbox dbox_colr=NULL;
static dbox dbox_pick=NULL;
static int *colr_pointer;
static int colr_number;

static int pick_colr[3];

void dbox_pick_handler(dbox d, void *handle)
/******************************************/
{
	int  button;
	int  colour;
	int  i;
	int *p;

	i = dbox_get(d);
	if(i < 0)
	{
		dbox_dispose(&d);
		dbox_pick = NULL;
		return;
	}

	button = i % 3;
	i = i / 3;
	p = &pick_colr[i];

	p[0] = dbox_getnumeric(d,i*3+2);
	if(button<=2)
	{
		if(dbox_persist())
			button ^= 1;

		if(button==0)
			p[0]++;
		else
			p[0]--;

	}
	if(p[0] < 0)
		p[0] = 0;
	if(p[0] > 15)
		p[0] = 15;

	dbox_setnumeric(d,i*3+2,p[0]);


	colour = (pick_colr[0] << 16) + (pick_colr[1] << 8) + (pick_colr[2]);
	*colr_pointer = colour * 0x11;


	wimp_set_icon_state(dbox_syshandle(dbox_colr),colr_number+7,0,0);
}   /* end of dbox_pick_handler */



void pick_colour(int *colr_ptr)
/*****************************/
{
	int  i;
	int  colr;

	if(colr_ptr == NULL)
	{
		if(dbox_pick != NULL)
			dbox_dispose(&dbox_pick);
		dbox_pick = NULL;
		return;
	}

	if(dbox_pick == NULL)
	{
		dbox_pick = dbox_new("ColrPick");
		dbox_eventhandler(dbox_pick, dbox_pick_handler, NULL);
	}

	colr_pointer = colr_ptr;
	colr = *colr_ptr >> 4;

	for(i=2; i>=0; i--)
	{
		pick_colr[i] = colr & 0xf;
		dbox_setnumeric(dbox_pick,i*3+2,pick_colr[i]);
		colr = colr >> 8;
	}
	dbox_showstatic(dbox_pick);
}   /* end of pick_colour */



void dbox_colr_selected(int *hits)
/********************************/
{
	int  hit;

	hit = hits[0];

	switch(dbox_menu_field)
	{
	case 3:
		dbox_setfield(dbox_colr,dbox_menu_field,textwindow_colrs[hit]);
		options.colours[0]=hit;
		change_display_mode2();
		break;
	}
}   /* end of dbox_colr_selected */




BOOL dbox_colr_raw_handler(dbox d, void *event, void *handle)
/***********************************************************/
{
	int  icon;
	int  x,y;
	int  colour;
	int  c;
	wimp_eventstr *e;
	wimp_mousestr *mouse;
	int  more;
	wimp_redrawstr r;
	wimp_icon idata;

	e = (wimp_eventstr *)event;

	switch (e->e)
	{
	case wimp_EREDRAW:
		r.w = e->data.o.w;
		wimp_redraw_wind(&r, &more);

		while(more)
		{
			/* display the colour patch  */

			x = r.box.x0 - r.scx;
			y = r.box.y1 - r.scy;

			for(icon=0; icon<12; icon++)
			{
				wimp_get_icon_info(r.w,icon+7,&idata);

				c = options.text_colrs[icon];
				colour = (c << 24) + ((c & 0xff00) << 8) + ((c & 0xff0000) >> 8);
				os_swi6(0x40743,colour,0,0,0,0,0);  /* SetGCOL */
				bbc_rectanglefill(x+idata.box.x0,y+idata.box.y0,idata.box.x1-idata.box.x0,idata.box.y1-idata.box.y0);
			}

			wimp_get_rectangle(&r, &more);
		}
		break;

	case wimp_EBUT:
		/* click on icon.  get icon number. */
		mouse = &e->data.but.m;
		switch(dbox_menu_field = mouse->i)
		{
		case 3:
			dbox_menu(wmenu_textwindow,dbox_colr_selected,mouse);
			return(TRUE);

		default:
			colr_number = dbox_menu_field - 7;
			if((colr_number >= 0) && (colr_number < 12))
			{
				pick_colour(&options.text_colrs[colr_number]);
				return(TRUE);
			}
		}
		break;
	}
	return(help_handler(event,HELP_COLR));
}   /* end of dbox_colr_raw_handler */





void dbox_colr_handler(dbox d, void *handle)
/*********************************************/
{
	int  i;
	int  *colours;
	wimp_redrawstr r;

	switch(dbox_get(d))
	{
	case 0:
		for(i=1; i<3; i++)
		{
			options.colours[i] = dbox_getnumeric(d,i+3);
		}
		options.define_text_colrs = dbox_getnumeric(d,6) ^ 1;
		change_display_mode2();
		options_save();
		if(dbox_persist())
			return;
		break;

	case 19:   /* set colours from defaults */
		if(options.colours[COLR_TEXTW]==3)
			colours = text_colrs_256_inv;
		else if(options.colours[COLR_TEXTW]==4)
			colours = text_colrs_256_green;
		else
			colours = text_colrs_256;

		for(i=0; i<10; i++)
			options.text_colrs[i] = colours[i];

		r.w = dbox_syshandle(dbox_colr);
		r.box.x0=0;
		r.box.x1 = 2000;
		r.box.y0=  -2000;
		r.box.y1=0;
		wimp_force_redraw(&r);
		return;
	}

	pick_colour(NULL);
	dbox_dispose(&dbox_colr);
	dbox_colr = NULL;
}   /* end of dbox_colr_handler */





void options_colours()
/********************/
{
	int  i;

	if(dbox_colr == NULL)
		dbox_colr = dbox_new("Colours");

	dbox_raw_eventhandler(dbox_colr,dbox_colr_raw_handler,NULL);
	dbox_eventhandler(dbox_colr, dbox_colr_handler, NULL);

	dbox_setfield(dbox_colr,3,textwindow_colrs[options.colours[0]]);

	for(i=1; i<3; i++)
	{
		dbox_setnumeric(dbox_colr,i+3,options.colours[i]);
	}

	dbox_setnumeric(dbox_colr,6,options.define_text_colrs ^ 1);
	dbox_hide(dbox_colr);
	dbox_showstatic(dbox_colr);
}   /* end of options_colours */



/**************************************************************************/

extern int speak_loaded;
extern int  speak_inhibit;

static menu menu_voice_names=0;
wimp_menustr *wmenu_voice_names=NULL;
static menu menu_voice_variants=0;
wimp_menustr *wmenu_voice_variants=NULL;
#define N_VOICE_LIST 60
#define N_VOICE_VARIANTS 40
char **voice_names;
char **voice_variants;
char voice_list[N_VOICE_LIST];
char voice_variant_list[N_VOICE_VARIANTS];
int  voice_selection_field;
static dbox dbox_speech = NULL;



int speak_load(void)
/*****************/
{
	os_error *error;
	static int  count=0;
	int  count2;
	char path[256];
	char buf[200];

	if(speak_inhibit)
		return(0);

	if(speak_loaded == 0)
	{
		error = os_swi1r(SWI_SPEAK+2,1,&count);
		if((error) || (count <= 0) || (count > 10))
			count = 1;

		read_os_variable("eSpeak$Dir",path,sizeof(path)-1);
		if(path[0] == 0)
		{
			// no eSpeak$Dir, use the copy inside Pluto
			read_os_variable("Pluto$Dir",path,sizeof(path)-1);
			set_os_variable("eSpeak$Dir",path);
		}

		sprintf(buf,"RMEnsure speak 3.47  RMLoad %s.SpeakMod",path);

		os_cli(buf);

		speak_loaded = 1;

		if(options.speak_speed_announce == 0)
		{
			options.speak_speed = 10;
			options.speak_speed_announce = 10;
			options.speak_volume = 10;
			options_save();
		}
		speak_set_params(options.speak_speed,options.speak_volume);
	}
	return(speak_loaded);
}   /* end of speak_load */





void make_voices_menu()
/**********************/
{
	int  i;
	int  count=0;
	int  count2=0;
	char buf[32];

	if(menu_voice_names != 0)
	{
		menu_dispose(&menu_voice_names,0);
	}
	if(menu_voice_variants != 0)
	{
		menu_dispose(&menu_voice_variants, 0);
	}

	menu_voice_names = menu_new("Voices","");
	menu_voice_variants = menu_new("Variants","");

	if(speak_loaded)
	{
		for(i=0; (i<N_VOICE_LIST) && (voice_names[i] != NULL); i++)
		{
			if(voice_names[i][0] != 0)
			{
				sprintf(buf,"%2d  %s",i,voice_names[i]);
				menu_extend(menu_voice_names,buf);
				voice_list[count++] = i;
			}
		}
		for(i=0; (i<N_VOICE_VARIANTS) && (voice_variants[i] != NULL); i++)
		{
			if(voice_variants[i][0] != 0)
			{
				sprintf(buf,"%2d  %s",i,voice_variants[i]);
				menu_extend(menu_voice_variants,buf);
				voice_variant_list[count2++] = i;
			}
		}
	}

	if(count==0)
	{
		menu_extend(menu_voice_names,"0");
		voice_list[0] = 0;
	}
	wmenu_voice_names = (wimp_menustr *)menu_syshandle(menu_voice_names);

	if(count2==0)
	{
		menu_extend(menu_voice_variants,"0");
		voice_variant_list[0] = 0;
	}
	wmenu_voice_variants = (wimp_menustr *)menu_syshandle(menu_voice_variants);

}   /* end of make_voices_menu */




void voice_selected(int *hits)
/****************************/
/* Called from unknown_event_handler.  Bodge to get menu on dialogue box */
{
	int voice_num;
	char variant_name[LEN_VOICE_NAME];
	char *p;
	char buf[80];

	if(voice_selection_field < 29)
	{
		voice_num = voice_selection_field - 3;
		dbox_setfield(dbox_speech,voice_selection_field,voice_names[hits[0]]);
	}
	else
	{
		voice_num = voice_selection_field - 29;
		if(strcmp(p = voice_variants[hits[0]], "(none)") == 0)
			p = "";
		dbox_setfield(dbox_speech, voice_selection_field, p);
	}
	dbox_getfield(dbox_speech, voice_num+3, voices.voicename[voice_num], sizeof(voices.voicename[0]));
	dbox_getfield(dbox_speech, voice_num+29, variant_name, sizeof(variant_name));

	if(variant_name[0] != 0)
	{
		sprintf(buf, "%s+%s", voices.voicename[voice_num],variant_name);
		strncpy0(voices.voicename[voice_num], buf, sizeof(voices.voicename[voice_num]));
	}
}   /* end of voice_selected */



BOOL speech_dbox_raw_handler(dbox d, void *event, void *handle)
/*************************************************************/
{
	int  i;
	wimp_eventstr *e;
	wimp_mousestr *mouse;

	e = (wimp_eventstr *)event;

	switch (e->e)
	{
	case wimp_EBUT:
		/* click on icon.  get icon number. */
		mouse = &e->data.but.m;
		switch(mouse->i)
		{
		case 3:   // voice name
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:
			if(wmenu_voice_names == NULL)
				break;

			event_clear_current_menu();
			wimp_create_menu(wmenu_voice_names,mouse->x - 40,mouse->y + 20);
			voice_selection_field = mouse->i;
			menu_expected = voice_selected;
			return(TRUE);

		case 29:   // voice variant
		case 30:
		case 31:
		case 32:
		case 33:
		case 34:
			if(wmenu_voice_names == NULL)
				break;

			event_clear_current_menu();
			wimp_create_menu(wmenu_voice_variants,mouse->x - 40,mouse->y + 20);
			voice_selection_field = mouse->i;
			menu_expected = voice_selected;
			return(TRUE);

		case 14:
			i = dbox_getnumeric(d,12) - 1;
			if(i < 1)
				i = 1;
			dbox_setnumeric(d,12,i);
			speak_set_params(i,0);
			return(TRUE);

		case 15:
			i = dbox_getnumeric(d,12) + 1;
			if(i > 25)
				i = 25;
			dbox_setnumeric(d,12,i);
			speak_set_params(i,0);
			return(TRUE);

		case 16:
			i = dbox_getnumeric(d,13) - 1;
			if(i < 1)
				i = 1;
			dbox_setnumeric(d,13,i);
			speak_set_params(0,i);
			return(TRUE);

		case 17:
			i = dbox_getnumeric(d,13) + 1;
			if(i > 20)
				i = 20;
			dbox_setnumeric(d,13,i);
			speak_set_params(0,i);
			return(TRUE);

		case 24:
			i = dbox_getnumeric(d,23) - 1;
			if(i < 1)
				i = 1;
			dbox_setnumeric(d,23,i);
			return(TRUE);

		case 25:
			i = dbox_getnumeric(d,23) + 1;
			if(i > 20)
				i = 20;
			dbox_setnumeric(d,23,i);
			return(TRUE);
		}
		break;

	}
	return(help_handler(event,HELP_OPSPEAK));
}   /* end of speech_dbox_raw_handler */




void dbox_speech_handler(dbox d, void *handle)
/********************************************/
{
	if(dbox_get(d) == 1)
	{
		options.speak_tayt = dbox_getnumeric(d,2);
		options.speak_title = dbox_getnumeric(d,11);
		options.speak_next = dbox_getnumeric(d,18);
		options.speak_next_unread = dbox_getnumeric(d,19);
		options.speak_announcements = dbox_getnumeric(d,9);
		options.speak_skip_addresses = dbox_getnumeric(d,10);
		options.speak_speed = dbox_getnumeric(d,12);
		options.speak_volume = dbox_getnumeric(d,13);
		options.speak_punct = dbox_getnumeric(d,20);
		options.speak_speed_announce = dbox_getnumeric(d,23);
		speak_set_params(options.speak_speed,options.speak_volume);

		options_save();
	}
	if(!dbox_persist())
	{
		dbox_dispose(&d);
		dbox_speech = NULL;
	}
}   /* end of dbox_speech_handler */







void options_speak()
/******************/
{
	dbox d;
	int  i;
	int  speakmod_version;
	char *variant;
	char voice_name[24];

	speak_load();

	if(dbox_speech != NULL)
	{
		d = dbox_speech;
		dbox_hide(dbox_speech);
	}
	else
	{
		d = dbox_new("Speak");
		dbox_speech = d;
	}

	dbox_raw_eventhandler(d,speech_dbox_raw_handler,NULL);
	dbox_eventhandler(d, dbox_speech_handler, NULL);

	/* get the voice name data */
	os_swi1r(SWI_SPEAK+2,0,(int *)&speakmod_version);

	if((speakmod_version >= 2) && (speakmod_version < 10))
	{
		os_swi2r(SWI_SPEAK+2,5,0,(int *)&voice_names, (int *)&voice_variants);

		for(i=0; i<6; i++)
		{
			strcpy(voice_name, voices.voicename[i]);
			variant = strchr(voice_name,'+');
			if(variant == NULL)
				variant = "";
			else
			{
				*variant++ = 0;
			}
			dbox_setfield(dbox_speech,i+3,voice_name);
			dbox_setfield(dbox_speech, i+29, variant);
		}

		/* make voice menu */
		make_voices_menu();
	}

	dbox_setnumeric(d,2,options.speak_tayt);
	dbox_setnumeric(d,11,options.speak_title);
	dbox_setnumeric(d,18,options.speak_next);
	dbox_setnumeric(d,19,options.speak_next_unread);
	dbox_setnumeric(d,9,options.speak_announcements);
	dbox_setnumeric(d,10,options.speak_skip_addresses);
	dbox_setnumeric(d,12,options.speak_speed);
	dbox_setnumeric(d,13,options.speak_volume);
	dbox_setnumeric(d,20,options.speak_punct);
	dbox_setnumeric(d,23,options.speak_speed_announce);

	dbox_hide(d);
	dbox_showstatic(d);

}   /* end of options_speak */




















/********************************************************************************/

void options_display_reload(char *fname)
/**************************************/
{
	char cmd[256];

	sprintf(cmd,"%smakedata e_display %s",pluto_path,fname);
	wimp_starttask(cmd);

	display_options_load();
}   /* end of options_display_reload */


/********************************************************************************/



void options_backup()
/*******************/
{
	int  diff;
	int  now_time[2];
	int  file_time[2];
	char path2[32];
	char path3[32];
	char path4[32];
	char path5[32];
	os_regset regs;

	sprintf(path2,"%sbackup.choices",pluto_path);
	sprintf(path3,"%sbackup.choices2",pluto_path);
	sprintf(path4,"%sbackup.log",pluto_path);
	sprintf(path5,"%sbackup.log2",pluto_path);

	/* get current date */
	regs.r[0] = 14;       /* OS_Word 14,3 */
	regs.r[1] = (int)now_time;
	now_time[0] = 3;      /* reason code */
	os_swi(0x07,&regs);

	get_time_stamp2(path2,(char *)file_time);

	diff = now_time[0] - file_time[0];   /* age of backup, in 1/100 sec */
	if((diff > 0) && (diff < (7*24*3600*100)))
		return;        /* less than 7 days since backup was last made */


	/* OS_FSControl 26, copy, */
	os_swi4(0x29+os_X,26,(int)path2,(int)path3,3);    /* previous version */
	os_swi4(0x29+os_X,26,(int)path_choices,(int)path2,3);

	os_swi2(0x08,9,(int)path2);   /* set timestamp */

	/* copy log file */
	remove(path5);
	file_move(path4,path5);

}   /* end of options_backup */




#define N_MAIL_BOX0  24   /* before version 1.11g */

void options_upgrade9()
/********************/
{
	int  ix;
	int  length;
	char *p;
	char *p2;
	int  count;

	OPTIONS_OLD *old_opts;

	length = sizeof(OPTIONS_OLD);
	if(sizeof(OPTIONS) < length)
		length = sizeof(OPTIONS);

	old_opts = calloc(sizeof(OPTIONS_OLD),1);
	memcpy(old_opts,&options,length);

	p = (char *)&options.text_colrs[8];
	p2 = &options.mailbox[N_MAIL_BOX0-1].email_addr[63];
	memset(p,0,p2-p);

	/*copy across the mailbox data */
	count = 0;
	for(ix=0; ix<N_MAIL_BOX0; ix++)
	{
		if(old_opts->mailbox[ix].user_id[0] == 0)
			continue;

		memcpy(&options.mailbox[ix],&old_opts->mailbox[ix],16);
		sprintf(options.mailbox[ix].email_addr,"%s@%s",
				old_opts->mailbox[ix].user_id,old_opts->mailbox[ix].domain);

		strcpy(options.mailbox[ix].full_name,old_opts->mailbox[ix].full_name);
		options.mailbox[ix].user_id_len = strlen(old_opts->mailbox[ix].user_id);
		count++;
	}
	options.n_mail_box = count;

	options.news_box = options.xnews_box;
	options.news_log = options.xnews_log;
	options.returned_box = options.xmaillist_box;
	options.text_box = options.xtext_box;
	options.filter_box = options.xjunk_box;

	options.xnews_box = 0;
	options.xnews_log = 0;
	options.xmaillist_box = 0;
	options.xtext_box = 0;
	options.xjunk_box = 0;

	options.mail_8bit = 0;
	options.addr_expand = 0;

	options.article_viewer_type = 1;
	options.autosave = 3;

	memcpy(options.news_in,old_opts->news_in,&options.save_path[150]-&options.news_in[0]);

	free(old_opts);

}   /* end of options_upgrade9 */


void options_upgrade10()
/**********************/
/* Version 1.06a  18.2.98 */
{
	/*   convert_boxes2(); */
}   /* end of ptions_upgrade10 */


void options_upgrade11()
/**********************/
/* Version 1.07   10.3.98 */
{
	options.text_colrs[8] = 0xeeeebb;
	options.text_colrs[9] = 0x55aaee;
}   /* end of options_upgrade11 */


void options_upgrade13()
/**********************/
/* Version 1.11d  26.2.99 */
{
	int  ix;
	char *p;
	OPTIONS_MAILBOX *m;

	/* make signature name from email address */
	for(ix=0; ix<N_MAIL_BOX0; ix++)
	{
		m = &options.mailbox[ix];
		p = get_user_id(m);
		strncpy(m->signature,make_legal_fname(p),sizeof(m->signature));
		m->signature[sizeof(m->signature)-1] = 0;
	}
}   /* end of options_upgrade13 */


void options_upgrade14()
/**********************/
/* Version 1.11g  27.3.99 */
{
	memset(&options.speak_voice[2],options.speak_voice_old[2],3);
	options.speak_voice[0] = options.speak_voice_old[0];
	options.speak_voice[1] = options.speak_voice_old[1];
	options.speak_voice[5] = options.speak_voice_old[3];

	memset(options.speak_voice_old,0,4);

	memset(&options.mailbox[24],0,sizeof(OPTIONS_MAILBOX)*8);
	options.tabs = 8;

}   /* end of options.upgrade14 */



void options_upgrade15()
/**********************/
/* Version 1.12   ??.7.99 */
{
	int  i;
	FILE *f;
	ART_FILE_HEADER art_header;
	char fname[80];

	options.text_colrs[10] = options.text_colrs[8];
	options.text_colrs[11] = options.text_colrs[9];
	options.text_colrs[8] = options.text_colrs[7];
	options.text_colrs[9] = options.text_colrs[4];

	remove("<pluto$dir>.Log");   /* now use <pluto$dir>.tmp.Log */
	remove("<pluto$dir>.ArticleSav");   /* now use <pluto$dir>.backup.articlesav */

	/* create articles files 32 to 63 */
	memset(&art_header,0,sizeof(art_header));
	art_header.version = ART_FILE_VERSION;
	for(i=32; i<=63; i++)
	{
		sprintf(fname,"%s.articles%d",pluto_articles,i);
		if(get_filelength(fname) <= 0)
		{
			f = fopen(fname,"w");
			fwrite(&art_header,1,sizeof(art_header),f);
			fclose(f);
		}
	}
}   /* end of options_upgrade12 */




int convert_boxes3()
/*******************/
/* For version 1.10e  9.1.99  */
{
	BOX_OLD2 *b1;
	BOX *b2;
	int log_box;
	int box;

	for(box=0; box<N_BOXES; box++)
	{
		b2 = &box_table[box];
		b1 = (BOX_OLD2 *)b2;

		if(b1->flags & 0x02)
			log_box = box;
		else
			log_box = 255;

		b2->flags = (b1->flags & 0x87);
		if(b1->editable) b2->flags |= BOX_EDITABLE;
		if(b1->leave_unread) b2->flags |= BOX_LEAVE_UNREAD;
		if(b1->archive_copy) b2->flags |= BOX_ARCHIVE_COPY;

		b2->log_box = log_box;
		b2->spare1 = 0;
		b2->spare2 = 0;
	}
	return(0);
}   /* end of convert_boxes3 */




void init_options()
/*****************/
{
	int  i;
	int updated = 0;
	char buf[128];


	/* is it time to backup the options file ? */
	options_backup();


	options_default();
	if(options_load() < 0)
		exit(6);


	if(options.options_version < 9)
	{
		options_upgrade9();
	}

	if(options.options_version < 10)
	{
		options_upgrade10();
	}

	if(options.options_version < 11)
	{
		options_upgrade11();
	}

	if(options.options_version < 12)
	{
		options.reset_av_position = 1;
		options.close_og_list = 1;
	}

	if(options.options_version < 13)
	{
		options_upgrade13();
	}

	if(options.options_version < 14)
	{
		options_upgrade14();
	}

	if(options.options_version < 15)
	{
		options_upgrade15();
	}

	if(options.options_version < 16)
	{
		/* Version 1.14   5.2.00  */
		options.new_to_unread = 0;
	}

	if(options.options_version < 17)
	{
		/* Version 2.01d  13.3.00  */
		options.keep_references = 4;  /* default */
		options.local_mail = 0;
	}

	if(options.options_version < 18)
	{
		options.draft_box = options.news_log;
	}

	if(options.options_version < 19)
	{
		sprintf(buf,"%s.Fetch",pluto_articles);
		remove(buf);
		options.filter_expire = 30;
		options.filter_show_tick = 0;
		options.filter_discard = -9000;
		options.filter_set_read = -9000;
		options.spare30[0] = 0;
		options.spare30[1] = 0;

	}

	if(options.options_version < 20)
	{
		options.index_autosave = 15;

		updated =1;
		options.options_version = 20;
	}

	/* NOTE: update value of option_version check in options_save */
	/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

	if(options.spell_depth == 0)
	{
		if(read_os_version() >= 0xa5)
			options.spell_depth = 3;
		else
			options.spell_depth = 2;
		options.spell_opts = 0x7;
		updated = 1;
	}
	if(options.reply_wordwrap < 40)
	{
		options.reply_wordwrap = 40;
		updated = 1;
	}

	if(options.use_mime > 2) options.use_mime = 0;

	if(options.position_y[3]==0)
	{
		options.position_x[0] = 2000;
		options.position_y[3] = 2000;
	}
	if(options.position_y[0]==0)
		options.position_y[0] = 2000;
	if(options.position_width[0]==0)
		options.position_width[0]=1300;
	if(options.position_width[1]==0)
		options.position_width[1]=1240;

	if(updated)
	{
		options_save();
	}


	change_display_mode(&options.d,0);


	for(i=0; i<16; i++)
	{
		*wmenu[i].ptr = (wimp_menustr *)menu_syshandle(menu_new(wmenu[i].name,wmenu[i].string));
	}

	dbox_mail = dbox_new("Mail");
	dbox_raw_eventhandler(dbox_mail,dbox_mail_raw_handler,NULL);
	dbox_eventhandler(dbox_mail, dbox_mail_handler, NULL);

}   /* end of init_options */




void check_articles_lock()
/************************/
{
	FILE *f;
	char fname[128];

	sprintf(fname,"%s.Lock",pluto_articles);
	f = fopen(fname,"w");
	if(f == NULL)
	{
		werr(1,"Pluto is already running.  %s is open",fname);
	}
}   /* end of check_articles_lock */





void init_menu()
/**************/
{
#ifdef ARGO_IMPORT
	static char *menustr_misc = "Compile references index, ImportVoyager";
#else
	static char *menustr_misc = "Compile references index";
#endif

	static char *menustr_main = ">Info,Lists,Preferences,Articles,Backups,New doc,>Statistics,Misc,Quit";

	static char *menustr_lists = "Address book,Categories,Distribution Lists,Filters,Mailing Lists,Newsgroups,PGP Keyring,Signatures,Sources,Users";
	static char *menustr_prefs = "News/Mail...,Delivery...,Misc...,Fonts...,Sorting,Speech...,Filters...,Colours...,>Spell check,Save positions";
	static char *menustr_articles = "Repair/compact,Compact all,Save index,Find fault,Expire articles,Delete duplicates,Change New to Unread";


	menu m;

	/* Create the main menu tree */
	menu_main = menu_new("Pluto",menustr_main);

	menu_prefs = menu_new("Preferences",menustr_prefs);

	if(pluto_slave)
	{
		menu_setflags(menu_prefs,1,0,1);   /* fade News/mail */
		menu_setflags(menu_prefs,2,0,1);   /* fade Delivery */
		menu_setflags(menu_prefs,3,0,1);   /* fade Misc */
	}

	menu_submenu(menu_main,3,menu_prefs);

	m = menu_new("Lists",menustr_lists);
	menu_submenu(menu_main,2,m);

	m = menu_new("Articles",menustr_articles);
	menu_submenu(menu_main,4,m);

	m = menu_new("Misc",menustr_misc);
	menu_submenu(menu_main,8,m);

	attach_menu1(1);


	if(pluto_slave)
	{
		menu_setflags(menu_main,2,0,1);   /* fade Lists */
		menu_setflags(menu_main,4,0,1);   /* fade articles */
	}
}   /* end of init_menu */






void initialise2()
/****************/
{
	char *path_choices_write;
	char buf[128];


	read_os_variable("Pluto$Dir2",buf,sizeof(buf));
	set_os_variable("Pluto$Dir",buf);

	if(read_os_variable("Pluto$Articles",pluto_articles,sizeof(pluto_articles)) != 0)
	{
		/* <Pluto$Articles> is not set, use the default */
		strcpy(pluto_articles,"<Pluto$Dir>.Articles");
	}

	/* read os version number */
	read_os_version();

	/* RISC_OSlib initialisation */
	/*****************************/
	wimpt_init(pluto_name);         /* Main Wimp initialisation */

	res_init(pluto_name);           /* Resources */
	resspr_init();                   /* Application sprites */

	template_use_fancyfonts();
	template_init();                 /* Templates */
	dbox_init();                     /* Dialogue boxes */
	msgs_init();
	flex_init();

//   _kernel_register_slotextend(flex_budge);

	win_register_event_handler(win_ICONBARLOAD, icon_load_handler, NULL);
	win_claim_idle_events(win_ICONBARLOAD);
	win_add_unknown_event_processor(unknown_event_handler,NULL);


	/* Set up the icon on the icon bar, and declare its event handlers */
	/*******************************************************************/
	baricon("!pluto",(int)resspr_area(), proc_iconclick);
	event_setmask(0x01);   /* we don't want pointer entering/leaving events */


	srand((int)time(NULL));
	check_mode();

	setlocale(LC_CTYPE,"ISO8859-1");

	path_choices_write = path_choices;
	sprintf(buf,"%s.Choices",path_choices2);
	if(get_filelength(buf) > 100)
	{
		/* !Boot.Choices directory exists for Pluto */
		path_choices = path_choices2;
		path_choices_write = "<choices$write>.Pluto";
	}
	sprintf(buf,"%s.Signatures",path_choices_write);
	if(get_filetype(buf) != 0x1000)
	{
		/* added  15.4.99 */
		file_move("<pluto$dir>.signature",buf);
	}

	/* check file lock to ensure only one copy accessing the articles files */
	if(pluto_lock)
		check_articles_lock();

}   /* end of initialise2 */

